/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.deployment;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.uml2.uml.Abstraction;
import org.eclipse.uml2.uml.Artifact;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.CommunicationPath;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Deployment;
import org.eclipse.uml2.uml.DeploymentSpecification;
import org.eclipse.uml2.uml.Device;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.ExecutionEnvironment;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.Manifestation;
import org.eclipse.uml2.uml.Node;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Realization;
import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.Usage;

import com.cea.papyrus.core.editor.EditpartFactoryBase;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.AnchorEditPart;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.core.editpart.StereotypePropertiesDisplayEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AbstractionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AssociationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ClassEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.CommentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ConstraintEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DataTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DependencyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationLiteralEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.GeneralizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.InstanceSpecificationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.InterfaceEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.LinkInstanceSpecificationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.OperationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageImportEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PrimitiveTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PropertyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.RealizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ReceptionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.SignalEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.SlotEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.UsageEditPart;
import com.cea.papyrus.diagram.deployment.editpart.ArtifactEditPart;
import com.cea.papyrus.diagram.deployment.editpart.ArtifactISEditPart;
import com.cea.papyrus.diagram.deployment.editpart.CommunicationPathEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeploymentDiagramEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeploymentEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeploymentSpecificationEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeploymentSpecificationISEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeviceEditPart;
import com.cea.papyrus.diagram.deployment.editpart.DeviceISEditPart;
import com.cea.papyrus.diagram.deployment.editpart.ExecutionEnvironmentEditPart;
import com.cea.papyrus.diagram.deployment.editpart.ExecutionEnvironmentISEditPart;
import com.cea.papyrus.diagram.deployment.editpart.ManifestationEditPart;
import com.cea.papyrus.diagram.deployment.editpart.NodeEditPart;
import com.cea.papyrus.diagram.deployment.editpart.NodeISEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Manages creation of controllers for deployment diagram elements.
 */
public class DeploymentDiagramGraphicalEditPartsFactory extends EditpartFactoryBase implements
		EditPartFactory {

	/**
	 * The model manager.
	 */
	protected ModelManager modelManager;

	/**
	 * The Constructor.
	 * 
	 * @param modelManager the model manager
	 */
	public DeploymentDiagramGraphicalEditPartsFactory(ModelManager modelManager) {
		this.modelManager = modelManager;
	}

	/**
	 * Creates the edit part.
	 * 
	 * @param obj the obj
	 * @param context the context
	 * 
	 * @return the edit part
	 */
	public EditPart createEditPart(EditPart context, Object obj) {
		//new mechanism
		EditPart result= getEditPartFromProperty(context, obj,modelManager);
		if (result!=null){
			return result;
		}
		// to identify the good editpart we need the nature of the object
		// graphEdge or graphNode and
		// uml Elment connected
		// case of a diagram
		if (obj instanceof Diagram) {
			return new DeploymentDiagramEditPart((Diagram) obj, modelManager);
		} else if (obj instanceof GraphNode) {
			if (((Uml1SemanticModelBridge) ((GraphNode) obj).getSemanticModel()) == null) {
				if (((GraphNode) obj).getSemanticParent() != null) {
					return new StereotypePropertiesDisplayEditPart(
							(GraphNode) obj, modelManager);
				}
				return new AnchorEditPart((GraphNode) obj, modelManager);
			}
			if ((((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement()) == null) {
				return new GraphNodeWithSemanticEditPart((GraphNode) obj,
						modelManager);
			}
			Element elt = ((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement();
			return searchEditPart((GraphNode) obj, elt);
		}

		// case of a graphEdge
		else if (obj instanceof GraphEdge) {
			if (((Uml1SemanticModelBridge) ((GraphEdge) obj).getSemanticModel()) != null) {
				if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof PackageImport) {
					return new PackageImportEditPart((GraphEdge) obj,
							modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Generalization) {
					return new GeneralizationEditPart((GraphEdge) obj,
							modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Deployment) {
					return new DeploymentEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Manifestation) {
					return new ManifestationEditPart((GraphEdge) obj,
							modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Usage){
					return new UsageEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Realization){
					return new RealizationEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Abstraction){
					return new AbstractionEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Dependency){
					return new DependencyEditPart((GraphEdge)obj,modelManager);

				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof CommunicationPath) {
					return new CommunicationPathEditPart((GraphEdge) obj,
							modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Association) {
					return new AssociationEditPart((GraphEdge) obj,
							modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof InstanceSpecification) {
					return new LinkInstanceSpecificationEditPart(
							(GraphEdge) obj, modelManager);
				}

			} else {
				GraphEdge ge = (GraphEdge) obj;
				return new GraphEdgeEditPart(ge, modelManager);
			}
		}

		return null;
	}

	/**
	 * Search edit part.
	 * 
	 * @param graphNode the graph node
	 * @param elt the elt
	 * 
	 * @return the edit part
	 */
	public EditPart searchEditPart(GraphNode graphNode, Element elt) {
		// Type elements
		if (elt instanceof ElementImport) {
			// in the case of element Import, we need to recall this method
			return searchEditPart(graphNode, ((ElementImport) elt)
					.getImportedElement());
		}
		// Interface
		if (elt instanceof Interface) {
			return new InterfaceEditPart(graphNode, modelManager);
		}
		// Constraint
		if (elt instanceof Constraint) {
			return new ConstraintEditPart(graphNode, modelManager);
		}
		// Signal
		if (elt instanceof Signal) {
			return new SignalEditPart(graphNode, modelManager);
		}
		// PrimitiveType
		if (elt instanceof PrimitiveType) {
			return new PrimitiveTypeEditPart(graphNode, modelManager);
		}
		// Enumeration
		if (elt instanceof Enumeration) {
			return new EnumerationEditPart(graphNode, modelManager);
		}
		// DataType
		if (elt instanceof DataType) {
			return new DataTypeEditPart(graphNode, modelManager);
		}
		// Enumeration Literal
		if (elt instanceof EnumerationLiteral) {
			return new EnumerationLiteralEditPart(graphNode, modelManager);
		}
		// Reception
		if (elt instanceof Reception) {
			return new ReceptionEditPart(graphNode, modelManager);
		}
		// Slot
		if (elt instanceof Slot) {
			return new SlotEditPart(graphNode, modelManager);
		}
		// DeploymentSpecification
		if (elt instanceof DeploymentSpecification) {
			return new DeploymentSpecificationEditPart(graphNode, modelManager);
		}
		// Artifact
		if (elt instanceof Artifact) {
			return new ArtifactEditPart(graphNode, modelManager);
		}
		// Device
		if (elt instanceof Device) {
			return new DeviceEditPart(graphNode, modelManager);
		}
		// ExecutionEnvironment
		if (elt instanceof ExecutionEnvironment) {
			return new ExecutionEnvironmentEditPart(graphNode, modelManager);
		}
		// Node
		if (elt instanceof Node) {
			return new NodeEditPart(graphNode, modelManager);
		}		
		// InstanceSpecifications
		if ( (elt instanceof InstanceSpecification) && 
			(((InstanceSpecification)elt).getClassifiers().isEmpty() == false) ) {		
			// DeviceInstanceSpecification
			if (((InstanceSpecification)elt).getClassifiers().get(0) instanceof Device){					
				return new DeviceISEditPart(graphNode, modelManager);
			}
			// ExecutionEnvironmentInstanceSpecification
			if (((InstanceSpecification)elt).getClassifiers().get(0) instanceof ExecutionEnvironment){					
				return new ExecutionEnvironmentISEditPart(graphNode, modelManager);
			}
			// NodeInstanceSpecification
			if (((InstanceSpecification)elt).getClassifiers().get(0) instanceof Node){					
				return new NodeISEditPart(graphNode, modelManager);
			}
			// ArtifactInstanceSpecification
			if (((InstanceSpecification)elt).getClassifiers().get(0) instanceof DeploymentSpecification) {
				return new DeploymentSpecificationISEditPart(graphNode, modelManager);		
			} 
			// ArtifactInstanceSpecification
			if (((InstanceSpecification)elt).getClassifiers().get(0) instanceof Artifact) {
				return new ArtifactISEditPart(graphNode, modelManager);		
			} 
			// InstanceSpecification
			return new InstanceSpecificationEditPart(graphNode,	modelManager);				
		}	
		// InstanceSpecification
		if ( (elt instanceof InstanceSpecification) && 
				(((InstanceSpecification)elt).getClassifiers().isEmpty() == true) )	{		
			return new InstanceSpecificationEditPart(graphNode,	modelManager);
		}
		// Class
		if (elt instanceof org.eclipse.uml2.uml.Class) {
			return new ClassEditPart(graphNode, modelManager);
		}
		// Property
		if (elt instanceof Property) {
			return new PropertyEditPart(graphNode, modelManager);
		}
		// Operation
		if (elt instanceof Operation) {
			return new OperationEditPart(graphNode, modelManager);
		}
		// Package
		if (elt instanceof Package) {
			return new PackageEditPart(graphNode, modelManager);
		}
		// Comment
		if (elt instanceof Comment) {
			return new CommentEditPart(graphNode, modelManager);
		}

		return null;
	}
}